#ifndef UNIT_TYPE_HPP_INCLUDED
#define UNIT_TYPE_HPP_INCLUDED

#include <boost/scoped_ptr.hpp>

#include <map>
#include <string>
#include <vector>

#include "unit_animation.hpp"
#include "unit_category.hpp"
#include "unit_modification.hpp"
#include "unit_type_fwd.hpp"
#include "wml_node_fwd.hpp"

namespace game {
class unit_type
{
public:
	static const_unit_type_ptr get(const std::string& id);

	virtual ~unit_type();

	virtual bool is_commander() const = 0;

	const std::string& description() const { return description_; }

	int attack() const;
	int defense() const;
	int aggression() const;
	int movement() const;
	int attack_range() const;

	enum FIGHTING_STYLE { FIGHTING_STYLE_MELEE, FIGHTING_STYLE_ARCHER };

	FIGHTING_STYLE fighting_style() const;

	const unit_animation& standing_animation() const { return standing_animation_; }
	const unit_animation& attack_animation() const;
	const unit_animation& defend_animation() const;
	const unit_animation& death_animation() const;
	const unit_animation* missile_animation() const;

	const std::string& portrait() const { return portrait_; }

	UnitCategory categories() const { return categories_; }

	const std::vector<const_unit_modification_ptr>& modifications() const { return modifications_; }

protected:
	static const_unit_type_ptr create(wml::const_node_ptr node);
	explicit unit_type(wml::const_node_ptr node);
private:
	std::string description_;
	int attack_, defense_, aggression_, movement_, attack_range_;

	FIGHTING_STYLE fighting_style_;

	unit_animation standing_animation_;
	boost::scoped_ptr<unit_animation> attack_animation_, defend_animation_, death_animation_, missile_animation_;

	std::string portrait_;

	UnitCategory categories_;

	std::vector<const_unit_modification_ptr> modifications_;
};

class soldier_unit_type : public unit_type
{
public:
	explicit soldier_unit_type(wml::const_node_ptr node);
	bool is_commander() const { return false; }
	int cost() const { return cost_; }
private:
	int cost_;
};

class commander_unit_type : public unit_type
{
public:
	explicit commander_unit_type(wml::const_node_ptr node);
	bool is_commander() const { return true; }

	int num_commands() const;
	int command_radius() const;
	int attack_bonus() const;
	int defense_bonus() const;

	const std::vector<const_soldier_unit_type_ptr>& recruits() const;

	struct level_info {
		level_info();
		explicit level_info(wml::const_node_ptr node);
		int experience_required;
		int attack, defense, attack_bonus, defense_bonus, command_radius;
	};

	const std::vector<level_info>& levels() const { return levels_; }

private:
	int num_commands_, command_radius_, attack_bonus_, defense_bonus_;

	std::vector<const_soldier_unit_type_ptr> recruits_;

	std::vector<level_info> levels_;
};

}

#endif
